import { Component, ReactNode } from 'react';
import { connect } from 'react-redux';
import {
  Breadcrumb,
  Layout,
  Flex,
  ConfigProvider,
  FloatButton,
  Collapse,
  Popconfirm,
  InputNumber,
  Dropdown,
  Descriptions,
  Form,
  Tooltip,
  Select,
  Divider,
  Table,
  message,
  Input,
  Space,
  Button,
} from 'antd';
import type { MenuProps } from 'antd';
import {
  EyeOutlined,
  DeleteOutlined,
  FileTextOutlined,
  MoreOutlined,
  SendOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import type { FormProps } from 'antd';
import { encode } from 'base-64';
import { cloneDeep } from 'lodash';

import MarkdownView from '@comp/markdown/show';
import {
  TABLE_VERSION_ITERATION_REQUEST_FIELDS,
  TABLE_VERSION_ITERATION_FIELDS,
  TABLE_MICRO_SERVICE_FIELDS,
  UNAME,
} from '@conf/db';
import { getdayjs, isStringEmpty } from '@rutil/index';
import { getPrjs } from '@act/project';
import {
  getVersionIterator,
  getOpenVersionIteratorsByPrj,
} from '@act/version_iterator';
import {
  getVersionIteratorFolders,
  delVersionIteratorFolder,
} from '@act/version_iterator_folders';
import {
  getVersionIteratorRequestsByProject,
  delVersionIteratorRequest,
  setVersionIterationRequestSort,
  batchMoveIteratorRequest,
  batchSetProjectRequestFold,
} from '@act/version_iterator_requests';
import { langFormat, langTrans } from '@lang/i18n';

const { Header, Content, Footer } = Layout;

type FieldType = {
  prj?: string;
  folder?: string;
  title?: string;
  uri?: string;
};

const colorsAddRequestApi = ['#fc6076', '#ff9a44', '#ef9d43', '#e75516'];
const colorsSendRequestApi = ['#6253e1', '#04befe'];
const getHoverColors = (colors: string[]) =>
  colors.map((color) => new TinyColor(color).lighten(5).toString());
const getActiveColors = (colors: string[]) =>
  colors.map((color) => new TinyColor(color).darken(5).toString());

let version_iterator_uuid = TABLE_VERSION_ITERATION_FIELDS.FIELD_UUID;
let version_iterator_title = TABLE_VERSION_ITERATION_FIELDS.FIELD_NAME;
let iteration_request_sort = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_SORT;
let version_iterator_prjs = TABLE_VERSION_ITERATION_FIELDS.FIELD_PROJECTS;
let version_iterator_content = TABLE_VERSION_ITERATION_FIELDS.FIELD_CONTENT;
let version_iterator_openflg = TABLE_VERSION_ITERATION_FIELDS.FIELD_OPENFLG;
let version_iterator_ctime = TABLE_VERSION_ITERATION_FIELDS.FIELD_CTIME;

let iteration_request_fold = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_FOLD;
let iteration_request_prj =
  TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_MICRO_SERVICE_LABEL;
let iteration_request_method =
  TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_REQUEST_METHOD;
let iteration_request_uri = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_URI;
let iteration_request_title =
  TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_TITLE;

let prj_label = TABLE_MICRO_SERVICE_FIELDS.FIELD_LABEL;
let prj_remark = TABLE_MICRO_SERVICE_FIELDS.FIELD_REMARK;

class RequestListVersion extends Component {
  constructor(props) {
    super(props);
    let iteratorId = this.props.match.params.id;
    this.state = {
      iteratorId,
      versionIteration: {},
      requestsJsxDividered: {},
      listColumn: [
        {
          title: langTrans('prj doc table field1'),
          dataIndex: iteration_request_uri,
          width: 150,
          render: (uri) => {
            if (uri.length > 50) {
              return (
                <Tooltip title={uri} placement="right">
                  {'...' + uri.substring(uri.length - 50, uri.length)}
                </Tooltip>
              );
            } else {
              return uri;
            }
          },
        },
        {
          title: langTrans('prj doc table field2'),
          dataIndex: iteration_request_title,
          width: 150,
        },
        {
          title: langTrans('prj doc table field3'),
          dataIndex: iteration_request_sort,
          width: 50,
          render: (sort, record) => {
            let prj = record[iteration_request_prj];
            let method = record[iteration_request_method];
            let uri = record[iteration_request_uri];
            if (sort === undefined) {
              return (
                <InputNumber
                  style={{ width: 65 }}
                  value={0}
                  onBlur={(event) =>
                    this.setApiSort(prj, method, uri, event.target.value)
                  }
                />
              );
            } else {
              return (
                <InputNumber
                  style={{ width: 65 }}
                  value={sort}
                  onBlur={(event) =>
                    this.setApiSort(prj, method, uri, event.target.value)
                  }
                />
              );
            }
          },
        },
        {
          title: langTrans('prj doc table field4'),
          key: 'operater',
          width: 50,
          render: (_, record) => {
            let docDetailUrl =
              '#/version_iterator_request/' +
              this.state.iteratorId +
              '/' +
              record[iteration_request_prj] +
              '/' +
              record[iteration_request_method] +
              '/' +
              encode(record[iteration_request_uri]);
            let sendRequestUrl =
              '#/internet_request_send_by_api/' +
              this.state.iteratorId +
              '/' +
              record[iteration_request_prj] +
              '/' +
              record[iteration_request_method] +
              '/' +
              encode(record[iteration_request_uri]);
            return (
              <Space size="middle">
                <Tooltip title={langTrans('prj doc table act1')}>
                  <Button
                    type="link"
                    icon={<SendOutlined />}
                    href={sendRequestUrl}
                  />
                </Tooltip>
                <Tooltip title={langTrans('prj doc table act2')}>
                  <Button
                    type="link"
                    icon={<EyeOutlined />}
                    href={docDetailUrl}
                  />
                </Tooltip>
                {this.state.versionIteration[version_iterator_openflg] === 1 ? (
                  <Dropdown menu={this.getMore(record)}>
                    <Button type="text" icon={<MoreOutlined />} />
                  </Dropdown>
                ) : null}
              </Space>
            );
          },
        },
      ],
      formReadyFlg: false,
      folders: [],
      prj: '',
      folder: null,
      movedRequests: [],
    };
  }

  async componentWillReceiveProps(nextProps) {
    let iteratorId = nextProps.match.params.id;
    if (this.state.iteratorId !== iteratorId) {
      let versionIteration = await getVersionIterator(iteratorId);
      this.setState({ iteratorId, versionIteration }, () => this.onFinish({}));
    }
  }

  componentDidMount() {
    if (this.props.prjs.length === 0) {
      getPrjs(this.props.dispatch);
    }
    this.onFinish({});
    getVersionIterator(this.state.iteratorId).then((versionIteration) =>
      this.setState({ versionIteration, formReadyFlg: true }),
    );
  }

  setApiSort = async (
    prj: string,
    method: string,
    uri: string,
    sort: number,
  ) => {
    setVersionIterationRequestSort(
      this.state.iteratorId,
      prj,
      method,
      uri,
      sort,
      () => {
        this.onFinish({
          prj: this.state.prj,
          folder: this.state.folder,
        });
      },
    );
  };

  setMovedRequests = (newMovedRequestKeys) => {
    this.state.movedRequests = newMovedRequestKeys;
    this.onFinish({
      prj: this.state.prj,
      folder: this.state.folder,
    });
  };

  getMore = (record: any): MenuProps => {
    return {
      items: [
        {
          key: '1',
          danger: true,
          label: (
            <Popconfirm
              title={langTrans('prj doc del title')}
              description={langTrans('prj doc del desc')}
              onConfirm={(e) => {
                delVersionIteratorRequest(record, () => {
                  this.onFinish({});
                });
              }}
              okText={langTrans('prj doc del sure')}
              cancelText={langTrans('prj doc del cancel')}
            >
              <Button danger type="link" icon={<DeleteOutlined />} />
            </Popconfirm>
          ),
        },
      ],
    };
  };

  onFinish: FormProps<FieldType>['onFinish'] = async (values) => {
    let prj = values?.prj;
    let title = values?.title;
    let uri = values?.uri;
    let folder = values?.folder;
    let version_iteration_requests = await getVersionIteratorRequestsByProject(
      this.state.iteratorId,
      prj,
      folder,
      title,
      uri,
    );
    let requestsDividered: any = {};
    let requestsJsxDividered: any = {};

    for (let version_iteration_request of version_iteration_requests) {
      version_iteration_request.key =
        version_iteration_request[iteration_request_method] +
        '$$' +
        version_iteration_request[iteration_request_uri];
      let prj = version_iteration_request[iteration_request_prj];
      if (!(prj in requestsDividered)) {
        requestsDividered[prj] = {};
        requestsJsxDividered[prj] = [];
        let versionIterators = (await getOpenVersionIteratorsByPrj(prj))
          .filter(
            (item) => item[version_iterator_uuid] != this.state.iteratorId,
          )
          .map((item) => {
            return {
              value: item[version_iterator_uuid],
              label: item[version_iterator_title],
            };
          });
        requestsJsxDividered[prj]['__iterators'] = versionIterators;
        requestsJsxDividered[prj]['__requests'] = [];
        let folders = await getVersionIteratorFolders(
          this.state.iteratorId,
          prj,
        );
        let oldFolders = this.state.folders;
        oldFolders[prj] = folders;
      }
      let fold = version_iteration_request[iteration_request_fold];
      if (!(fold in requestsDividered[prj])) {
        requestsDividered[prj][fold] = [];

        let foldJsx = {};
        foldJsx.key = fold;
        foldJsx.label = '/' + fold;
        foldJsx.children = (
          <Table
            rowSelection={{
              selectedRowKeys: this.state.movedRequests,
              onChange: this.setMovedRequests,
            }}
            dataSource={requestsDividered[prj][fold]}
            columns={this.state.listColumn}
          />
        );
        foldJsx.extra =
          !isStringEmpty(fold) &&
          this.state.versionIteration[version_iterator_openflg] === 1 ? (
            <DeleteOutlined
              onClick={(event) => {
                delVersionIteratorFolder(
                  this.state.iteratorId,
                  prj,
                  fold,
                  async () => {
                    message.success('删除文件夹成功');
                    let folders = await getVersionIteratorFolders(
                      this.state.iteratorId,
                      prj,
                    );
                    let oldFolders = this.state.folders;
                    oldFolders[prj] = folders;
                    this.setState({ folders: cloneDeep(this.state.folders) });
                    this.onFinish({});
                  },
                );
                event.stopPropagation();
              }}
            />
          ) : null;

        requestsJsxDividered[prj]['__requests'].push(foldJsx);
      }
      requestsDividered[prj][fold].push(version_iteration_request);
    }
    for (let _prj in requestsJsxDividered) {
      for (let requestJsxDividered of requestsJsxDividered[_prj]) {
        let fold = requestJsxDividered.key;
        requestJsxDividered.label =
          '/' + fold + '（' + requestsDividered[_prj][fold].length + '）';
      }
    }
    this.setState({
      requestsJsxDividered,
      prj,
      folder,
    });
  };

  render(): ReactNode {
    return (
      <Layout>
        <Header style={{ padding: 0 }}>{langTrans('version doc title')}</Header>
        {this.state.formReadyFlg ? (
          <Content style={{ padding: '0 16px', width: 'calc(100% - 16px)' }}>
            <Breadcrumb
              style={{ margin: '16px 0' }}
              items={[
                { title: langTrans('version doc bread1') },
                { title: langTrans('version doc bread2') },
              ]}
            />
            <Descriptions
              column={2}
              title={langTrans('version doc desc title')}
              items={[
                {
                  key: version_iterator_title,
                  label: langTrans('version doc desc1'),
                  children: this.state.versionIteration[version_iterator_title],
                },
                {
                  key: version_iterator_openflg,
                  label: langTrans('version doc desc2'),
                  children:
                    this.state.versionIteration[version_iterator_openflg] === 1
                      ? langTrans('version doc status1')
                      : langTrans('version doc status2'),
                },
                {
                  key: UNAME,
                  label: langTrans('version doc desc3'),
                  children: this.state.versionIteration[UNAME],
                },
                {
                  key: version_iterator_ctime,
                  label: langTrans('version doc desc4'),
                  children: getdayjs(
                    this.state.versionIteration[version_iterator_ctime],
                  ).format('YYYY-MM-DD'),
                },
              ]}
            />
            <Flex justify="flex-start" align="center" gap="middle">
              <Form
                layout="inline"
                onFinish={this.onFinish}
                initialValues={{ prj: this.state.prj }}
                autoComplete="off"
              >
                <Form.Item<FieldType>
                  style={{ paddingBottom: 20 }}
                  label={langTrans('prj doc operator1')}
                  name="uri"
                  rules={[{ required: false }]}
                >
                  <Input />
                </Form.Item>

                <Form.Item<FieldType>
                  label={langTrans('prj doc operator2')}
                  name="title"
                  rules={[{ required: false }]}
                >
                  <Input />
                </Form.Item>

                <Form.Item<FieldType>
                  label={langTrans('version doc operator1')}
                  name="prj"
                  rules={[{ required: false }]}
                >
                  <Select
                    style={{ width: 180 }}
                    options={this.state.versionIteration[
                      version_iterator_prjs
                    ].map((item) => {
                      return {
                        value: item,
                        label: this.props.prjs.find(
                          (row) => row[prj_label] === item,
                        )
                          ? this.props.prjs.find(
                              (row) => row[prj_label] === item,
                            )[prj_remark]
                          : '',
                      };
                    })}
                    onChange={async (value) => {
                      this.setState({ prj: value });
                    }}
                  />
                </Form.Item>

                <Form.Item<FieldType>
                  label={langTrans('version doc operator2')}
                  name="folder"
                  rules={[{ required: false }]}
                >
                  <Select
                    style={{ width: 180 }}
                    options={this.state.folders[this.state.prj]}
                  />
                </Form.Item>

                <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
                  <Button htmlType="submit">{langTrans('prj doc btn')}</Button>
                </Form.Item>
              </Form>
              <Flex vertical justify="flex-start" align="center" gap="middle">
                <ConfigProvider
                  theme={{
                    components: {
                      Button: {
                        colorPrimary: `linear-gradient(90deg,  ${colorsAddRequestApi.join(
                          ', ',
                        )})`,
                        colorPrimaryHover: `linear-gradient(90deg, ${getHoverColors(
                          colorsAddRequestApi,
                        ).join(', ')})`,
                        colorPrimaryActive: `linear-gradient(90deg, ${getActiveColors(
                          colorsAddRequestApi,
                        ).join(', ')})`,
                        lineWidth: 0,
                      },
                    },
                  }}
                >
                  <Button
                    type="primary"
                    href={'#/interator_add_request/' + this.state.iteratorId}
                    // size="large"
                  >
                    {langTrans('version doc btn2')}
                  </Button>
                </ConfigProvider>

                <ConfigProvider
                  theme={{
                    components: {
                      Button: {
                        colorPrimary: `linear-gradient(135deg,  ${colorsSendRequestApi.join(
                          ', ',
                        )})`,
                        colorPrimaryHover: `linear-gradient(135deg, ${getHoverColors(
                          colorsSendRequestApi,
                        ).join(', ')})`,
                        colorPrimaryActive: `linear-gradient(135deg, ${getActiveColors(
                          colorsSendRequestApi,
                        ).join(', ')})`,
                        lineWidth: 0,
                      },
                    },
                  }}
                >
                  <Button
                    type="primary"
                    href={
                      '#/internet_request_send_by_iterator/' +
                      this.state.iteratorId
                    }
                    // size="large"
                  >
                    {langTrans('version doc btn1')}
                  </Button>
                </ConfigProvider>
              </Flex>
            </Flex>
            {Object.keys(this.state.requestsJsxDividered).map((prj) =>
              this.props.prjs.length > 0 &&
              this.props.prjs.find((row) => row[prj_label] === prj) ? (
                <div key={prj}>
                  <Divider orientation="left">
                    <p>
                      {langFormat('version doc project', {
                        name:
                          this.props.prjs.length > 0
                            ? this.props.prjs.find(
                                (row) => row[prj_label] === prj,
                              )[prj_remark]
                            : '',
                      })}
                    </p>
                  </Divider>
                  <Form layout="inline" style={{ marginBottom: 16 }}>
                    <Form.Item label={langTrans('version doc operator3')}>
                      <Select
                        style={{ minWidth: 130 }}
                        onChange={(value) => {
                          batchMoveIteratorRequest(
                            this.state.iteratorId,
                            prj,
                            this.state.movedRequests,
                            value,
                            () => {
                              this.state.movedRequests = [];
                              message.success('移动迭代成功');
                              this.onFinish({
                                prj: this.state.prj,
                                folder: this.state.folder,
                              });
                            },
                          );
                        }}
                        options={
                          this.state.requestsJsxDividered[prj]['__iterators']
                        }
                      />
                    </Form.Item>
                    <Form.Item label={langTrans('version doc operator4')}>
                      <Select
                        style={{ minWidth: 130 }}
                        onChange={async (value) => {
                          await batchSetProjectRequestFold(
                            this.state.iteratorId,
                            prj,
                            this.state.movedRequests,
                            value,
                          );
                          this.state.movedRequests = [];
                          this.onFinish({
                            title: this.state.title,
                            uri: this.state.uri,
                          });
                        }}
                        dropdownRender={(menu) => (
                          <>
                            {menu}
                            <Divider style={{ margin: '8px 0' }} />
                            <Input
                              placeholder="回车新建文件夹"
                              onKeyDown={(e) => {
                                if (e.key === 'Enter') {
                                  this.handleCreateFolder(e.target.value);
                                  e.target.value = '';
                                }
                                e.stopPropagation();
                              }}
                            />
                          </>
                        )}
                        options={this.state.folders[prj]}
                      />
                    </Form.Item>
                  </Form>
                  <Collapse
                    items={this.state.requestsJsxDividered[prj]['__requests']}
                  />
                </div>
              ) : null,
            )}
            {/* <Flex>
              <Divider>{langTrans('version doc md title')}</Divider>
            </Flex>
            <MarkdownView
              showNav={true}
              content={this.state.versionIteration[version_iterator_content]}
              show={this.state.formReadyFlg}
              width={630}
            /> */}
            <FloatButton
              icon={<FileTextOutlined />}
              description={langTrans('doc btn1')}
              shape="square"
              style={{ right: 24, width: 60 }}
              onClick={() =>
                (window.location.href =
                  '#/version_iterator_doc/' + this.state.iteratorId)
              }
            />
          </Content>
        ) : null}
        <Footer style={{ textAlign: 'center' }}>
          ApiChain ©{new Date().getFullYear()} Created by
        </Footer>
      </Layout>
    );
  }
}

function mapStateToProps(state) {
  return {
    prjs: state.prj.list,
  };
}

export default connect(mapStateToProps)(RequestListVersion);
